/**
 * @file categories/construction/cf1697d/main.cpp
 * @brief
 * @see
 * @tags construction string binary-search
 * @author Ruiming Guo (guoruiming@stu.scu.edu.cn)
 * @copyright 2022
 * @date 2022/7/3 08:38:25
 **/

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;

char ask_character(int i) {
  cout << "? 1 " << i << endl;
  string s;
  cin >> s;
  return s[0];
}

int ask_count(int l, int r) {
  cout << "? 2 " << l << ' ' << r << endl;
  int x;
  cin >> x;
  return x;
}

int main() {
  // High rating and good luck!
  int n;
  cin >> n;
  string s;
  vector<vector<int>> cnt(n + 1);
  for (int i = 0; i < n; ++i) {
    if (i == 0) {
      s.push_back(ask_character(1));
      cnt[0] = {1};
    } else {
      int cur = ask_count(1, i + 1);  // 出现次数
      if (cur > cnt[i - 1][0])
        s.push_back(ask_character(i + 1));  // 全新的字符
      else {                                // 不是新的字符
        map<char, int> last;                // 每个字符最后出现的位置
        for (int j = 0; j < s.size(); ++j) {
          last[s[j]] = j;
        }
        vector<int> lasts;
        for (auto x : last) lasts.push_back(x.second);
        sort(lasts.begin(), lasts.end());
        int l = 0;
        int r = (int)lasts.size();
        // There is always an occurrence in [lasts[l], i)
        // There is no occurrence in [lasts[r], i)
        while (r - l > 1) {
          int m = (l + r) / 2;
          int c = ask_count(lasts[m] + 1, i + 1);
          if (c == cnt[i - 1][lasts[m]])
            l = m;
          else
            r = m;
        }
        s.push_back(s[lasts[l]]);
      }
      cnt[i].resize(i + 1);
      set<char> q;
      for (int j = i; j >= 0; --j) {
        q.insert(s[j]);
        cnt[i][j] = q.size();
      }
    }
  }
  cout << "! " << s << endl;
  cout.flush();
  return 0;
}
